﻿@page "/"
@inject HttpClient HttpClient
@inject IJSRuntime  JSRuntime
@inject MessageService _message
@inject NavigationManager navigationManager
@inject IConfiguration configure

<div class="submit-blog-container">
    <TextArea OnChange="@(e => TextAreaOnChange())" Placeholder="发表动态" @bind-Value="@BlogText" />
    <Popover Placement="@PlacementType.BottomLeft" OnVisibleChange="OnVisibleChange" Visible="_visible" Title="图片" Trigger="new TriggerType[] { TriggerType.Click }">
        <ChildContent>
    <Icon Style="font-size:30px" Type="picture" Theme="outline" />
        </ChildContent>
    <ContentTemplate>
        <div>
        <Upload Action="@(APIUrl + "/api/blog/public-method/upload-file")"
                Name="file"
                @bind-FileList="fileList"
                ShowButton="fileList?.Count < 8"
                BeforeUpload="BeforeUpload"
                ListType="picture-card"
                OnPreview="(file)=> {
                           Console.WriteLine(file.FileName);
                           Console.WriteLine(file.Url);
                           previewVisible = true;
                           previewTitle = file.FileName;
                           imgUrl = file.Url;
                       }"
                OnChange="HandleChange"
                Headers="@AuthHeader"
                Data="@UploadDto">
            <div>
                <Icon Type="plus"></Icon>
                <div className="ant-upload-text">点击上传</div>
            </div>
        </Upload>
        <Modal Visible="previewVisible"
               Title="预览图片"
               OnCancel="()=> previewVisible=false">
            <img style="width: 100%" src="@imgUrl" />
        </Modal>
        <a @onclick="_ => this._visible = false">关闭</a>
    </div>
    </ContentTemplate>
</Popover>
    <button class="reply-submit" @onclick="@(() => SubmitBlog())">发表动态</button>
</div>
<AntList Class="demo-loadmore-list" DataSource="@BlogList" ItemLayout="ListItemLayout.Horizontal" Loading="@InitLoading">
    <ChildContent Context="item">
        <div class="blog-list">
            <ListItem>
                <ListItemMeta Avatar="@item.HeadPhoto" Description="">
                    <TitleTemplate>
                        <a href="/usercenter/@item.UserName">@item.Name</a>&nbsp;&nbsp;&nbsp;<span style="color:#949494;font-weight:300">@item.CreateTime.ToString("yyyy-MM-dd HH:mm:ss")</span>
                    </TitleTemplate>
                </ListItemMeta>
                <pre class="blog-content">@item.Content</pre>
                        @{
                            if (!string.IsNullOrEmpty(item.Files))
                            {
                                <div>
                                <ImagePreviewGroup>
                                @{var imgList = item.Files.Split(',');
                                foreach (var img in imgList)
                                {
                                    if (!string.IsNullOrEmpty(img))
                                    {
                                        <Image Width="200" Src="@img" />
}
                                }
                                }
                                </ImagePreviewGroup></div>
                            }
                        }
                <ul class="blog-list-action">
                    <li>
                        <a @onclick="@(() => GiveLike(item.Id))">
                            <Space>
                                <SpaceItem><Icon Type="like" /></SpaceItem>
                                <SpaceItem>@item.LikeCount.ToString()</SpaceItem>
                            </Space>
                        </a>
                    </li>
                    <li>
                        <a @onclick="@(() => { item.showReply = !item.showReply; })">
                            <Space>
                                <SpaceItem><Icon Type="message" /></SpaceItem>
                                <SpaceItem>@item.ReplyList.Count.ToString()</SpaceItem>
                            </Space>
                        </a>
                    </li>
                    @if (userInfo != null)
                    {
                        if (userInfo.Id == item.UserId || userInfo.Roles.Contains("admin"))
                        {
                            <li>
                                <Popconfirm Title="是否删除？"
                                            OnConfirm="@(() => DeleteBlog(item.Id))"
                                            OnCancel="(() => { })"
                                            OkText="确定"
                                            CancelText="取消">
                                    <Unbound>
                                        <a @ref="@context.Current">
                                            <Space>
                                                <Icon Type="delete" Theme="outline" />
                                            </Space>
                                        </a>
                                    </Unbound>
                                </Popconfirm>
                            </li>
                        }
                    }
                    }
                </ul>
            </ListItem>
            @if (item.showReply)
            {
                <AntList DataSource="@item.ReplyList" Class="comment-list">
                    <Header>
                        <div class="reply-send">
                            <div @onclick="@(() => HeadNavTo())" class="user-face"><Avatar Size="48" Src="@ReplySentFace" /></div>
                            <div class="reply-container">
                                <TextArea OnChange="@(e => TextAreaOnChange())" Placeholder="发表评论" @bind-Value="@ReplySentText" />
                                <button class="reply-submit" @onclick="@(() => SentReply(item.Id))">发表评论</button>
                            </div>
                        </div>
                    </Header>
                    <ChildContent>
                        <ListItem>
                            <Comment Avatar="@context.HeadPhoto" Author="@context.Name" Datetime="@context.CreateTime.ToString("yyyy-MM-dd HH:mm:ss")" ContentTemplate="@RenderReplyString(context.Content, context.ReplyToUserName, context.ReplyToName)"></Comment>
                            <a @onclick="@(() => SetReplyPara(context.BlogReplyId, context.Name))">回复</a>
                            @if (userInfo != null)
                            {
                                @if (userInfo.Id == item.UserId || userInfo.Roles.Contains("admin") || context.ReplyUserId == userInfo.Id)
                                {
                                    <Popconfirm Context = "context1" Title="是否删除？"
                                            OnConfirm="@(() => DeleteReply(context.BlogReplyId, item.Id))"
                                            OnCancel="(() => { })"
                                            OkText="确定"
                                            CancelText="取消">
                                    <Unbound>
                                        <a @ref="@context1.Current">
                                           <Icon Type="delete" Theme="outline" />
                                        </a>
                                    </Unbound>
                                </Popconfirm>
                                }
                            }
                        </ListItem>
                    </ChildContent>
                </AntList>
            }
        </div>
    </ChildContent>
    <LoadMore>
        @if (!InitLoading && !Loading && !NoMore)
        {
            <div class="demo-loadmore-btn-content ">
                <Button OnClick="OnLoadMore">加载更多</Button>
            </div>
        }
        @if (NoMore)
        {
            <div style="text-align:center;margin-top:20px;">
                <h4>只有这么多啦~</h4>
            </div>
        }
    </LoadMore>
</AntList>

<style>
    .blog-content {
        margin-left: 48px;
        margin-top: 3px;
        font-size: 14px;
        font-family: "微软雅黑";
    }

    .demo-loadmore-list {
        width: 100%;
        background-color: #fff;
        border: 1px solid #e5e9ef;
        padding-bottom: 20px;
        /*margin: 10px 0 10px 521px;*/
    }

        .demo-loadmore-list > ul {
            margin: 0;
        }

    .demo-loadmore-btn-content {
        text-align: center;
        margin-top: 12px;
        height: 32px;
        line-height: 32px;
    }

    .ant-list-item {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        justify-content: space-between;
    }

    .comment-list {
        margin-left: 45px;
    }

    .blog-list-action {
        flex: 0 0 auto;
        margin-left: 48px;
        padding: 0;
        font-size: 0;
    }

        .blog-list-action > li:first-child {
            padding-left: 0;
        }

        .blog-list-action > li {
            position: relative;
            display: inline-block;
            padding: 0 8px;
            color: rgba(0,0,0,.45);
            font-size: 14px;
            line-height: 1.5715;
            text-align: center;
        }

    .user-face {
        float: left;
        margin: 7px 0 0 5px;
        position: relative;
    }

    .reply-container {
        position: relative;
        margin-left: 85px;
        margin-right: 80px;
    }

        .reply-container > textarea {
            font-size: 12px;
            display: inline-block;
            box-sizing: border-box;
            background-color: #f4f5f7;
            border: 1px solid #e5e9ef;
            overflow: auto;
            border-radius: 4px;
            color: #555;
            width: 100%;
            height: 65px;
            transition: 0s;
            padding: 5px 10px;
            outline: none;
            resize: none
        }

    .reply-submit {
        width: 70px;
        height: 64px;
        position: absolute;
        right: -80px;
        top: 0;
        padding: 4px 15px;
        font-size: 14px;
        color: #fff;
        border-radius: 4px;
        text-align: center;
        min-width: 60px;
        vertical-align: top;
        cursor: pointer;
        background-color: #00a1d6;
        border: 1px solid #00a1d6;
        transition: 0.1s;
        user-select: none;
        outline: none;
    }

    .blog-list {
        margin: 0 21px;
    }

    .submit-blog-container {
        position: relative;
        margin: 10px 0 10px 10px;
        width: 90%;
    }

        .submit-blog-container > textarea {
            font-size: 12px;
            display: inline-block;
            box-sizing: border-box;
            background-color: #f4f5f7;
            border: 1px solid #e5e9ef;
            overflow: auto;
            border-radius: 4px;
            color: #555;
            width: 100%;
            height: 65px;
            transition: 0s;
            padding: 5px 10px;
            outline: none;
            resize: none
        }
        .ant-upload-select-picture-card i {
        color: #999;
        font-size: 32px;
    }

    .ant-upload-select-picture-card .ant-upload-text {
        margin-top: 8px;
        color: #666;
    }
</style>

@code {
    static RenderFragment replyRender =@<span>回复</span>;
    private RenderFragment _upPictureFrom =>
    @<div>
        <Upload Action="@(APIUrl + "/api/blog/public-method/upload-file")"
                Name="file"
                @bind-FileList="fileList"
                ShowButton="fileList?.Count < 8"
                BeforeUpload="BeforeUpload"
                ListType="picture-card"
                OnPreview="(file)=> {
                           Console.WriteLine(file.FileName);
                           Console.WriteLine(file.Url);
                           previewVisible = true;
                           previewTitle = file.FileName;
                           imgUrl = file.Url;
                       }"
                OnChange="HandleChange"
                Headers="@AuthHeader"
                Data="@UploadDto">
            <div>
                <Icon Type="plus"></Icon>
                <div className="ant-upload-text">Upload</div>
            </div>

        </Upload>
        <Modal Visible="previewVisible"
               Title="预览图片"
               OnCancel="()=> previewVisible=false">
            <img style="width: 100%" src="@imgUrl" />
        </Modal>
        <a @onclick="_ => this._visible = false">关闭</a>
    </div>;

    public class BlogListDto : BlogResultDto
    {
        public bool showReply { get; set; }
    }

    public bool InitLoading { get; set; } = true;
    public bool Loading { get; set; } = false;
    public bool NoMore { get; set; } = false;
    public List<BlogListDto> BlogList { get; set; }
    public GetBlogListDto BlogDto { get; set; } = new GetBlogListDto() { SkipCount = 0, MaxResultCount = 5 };
    public UserInfoDto userInfo { get; set; }
    public string ReplySentFace { get; set; }
    public string ReplySentText { get; set; }
    public int? ReplyToId { get; set; }
    public string SelfUrl => configure.GetSection("App")["SelfUrl"];
    public string AuthUrl => configure.GetSection("AuthServer")["Authority"];
    public string BlogText { get; set; }
    public string BlogPictures { get; set; } 
    private bool _visible = false;
bool previewVisible = false;
string previewTitle = string.Empty;
string imgUrl = string.Empty;
public Dictionary<string, string> AuthHeader = new Dictionary<string, string>();
public string APIUrl => configure.GetSection("API")["Url"];
public Dictionary<string, object> UploadDto = new Dictionary<string, object>()
{
            {"FileType",1 }
        };
        List<UploadFileItem> fileList = new List<UploadFileItem>
{
    };

    protected override async Task OnInitializedAsync()
    {
        string userString = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "userinfo");
        if (userString == null)
            ReplySentFace = "/img/defaultHeadPhoto.jpg";
        else
        {
            userInfo = JsonSerializer.Deserialize<UserInfoDto>(userString);
            ReplySentFace = userInfo.HeadPhoto;
            AuthHeader = new Dictionary<string, string>()
  {
                    { "Authorization", await JSRuntime.InvokeAsync<string>("localStorage.getItem", "Authorization")}
                };
        }
        BlogList = (await GetBlogList(BlogDto)).Items.ToList();
        BlogList.ForEach(t => t.showReply = t.ReplyList.Count > 0);
        BlogDto.SkipCount += BlogDto.MaxResultCount;
        InitLoading = false;
        await base.OnInitializedAsync();
    }

    /// <summary>
    /// 加载更多
    /// </summary>
    /// <returns></returns>
    public async Task OnLoadMore()
    {
        Loading = true;
        var respone = await GetBlogList(BlogDto);
        var res = respone.Items;
        BlogList.AddRange(res);
        if (respone.TotalCount == 0)
            NoMore = true;
        Loading = false;
    }

    /// <summary>
    /// 获取博客列表
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    public async Task<PagedResultDto<BlogListDto>> GetBlogList(GetBlogListDto dto)
    {
        string url = $"/api/blog/blog/blog-list?SkipCount={dto.SkipCount}&MaxResultCount={dto.MaxResultCount}";
        var res = await HttpClient.GetFromJsonAsync<PagedResultDto<BlogListDto>>(url);
        return res;
    }

    /// <summary>
    /// 渲染回复格式
    /// </summary>
    /// <param name="content"></param>
    /// <param name="username"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    public RenderFragment RenderReplyString(string content, string username, string name)
    {
        RenderFragment render;
        if (string.IsNullOrEmpty(username))
        {
            render = 
    @<span>@content</span>;
        }
        else if (username == "评论已被删除")
        {
            render = @<span>回复 @@@name  :@content</span>;
        }
        else
        {
            render = @<span>回复 <a href="/usercenter/@username" style="color:#00a1d6">@@@name</a>  :@content</span>
    ;
        }
        return render;
    }

    /// <summary>
    /// 渲染发表回复的格式
    /// </summary>
    /// <param name="replyToId"></param>
    /// <param name="name"></param>
    public void SetReplyPara(int? replyToId, string name)
    {
        if (replyToId != null)
        {
            ReplySentText = $"回复 @{name}  :";
            ReplyToId = replyToId;
        }
    }
    /// <summary>
    /// 退格发表评论的格式渲染
    /// </summary>
    public void TextAreaOnChange()
    {
        if (!string.IsNullOrEmpty(ReplySentText))
        {
            if (ReplySentText.StartsWith("回复 @"))
            {
                int delIndex = ReplySentText.IndexOf(':');
                Console.WriteLine(ReplySentText[(delIndex + 1)..]);
                if (delIndex == -1)
                {
                    ReplySentText = "";
                    ReplyToId = null;
                }
            }
        }
    }
    /// <summary>
    /// 提交回复
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task SentReply(int id)
    {
        if (userInfo == null)
        {
            await _message.Info("请登录");
            return;
        }
        string url = "/api/blog/blog/reply";
        BlogReplyDto dto = new BlogReplyDto
        {
            Content = ReplySentText,
            ReplyToId = ReplyToId,
            BlogId = id
        };
        StringContent content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json");
        var result = await HttpClient.PostAsync(url, content);
        if (result.IsSuccessStatusCode)
        {
            BlogReplyResultDto reply = await result.Content.ReadFromJsonAsync<BlogReplyResultDto>();
            reply.UserName = userInfo.UserName;
            reply.Name = userInfo.Name;
            reply.HeadPhoto = userInfo.HeadPhoto;
            BlogList.Find(t => t.Id == id).ReplyList.Add(reply);
            ReplySentText = "";
            await _message.Success("发表成功");
        }
        else
            await _message.Error("发表失败");
    }
    /// <summary>
    /// 头像跳转到个人空间
    /// </summary>
    /// <returns></returns>
    public async Task HeadNavTo()
    {
        if (userInfo != null)
        {
            navigationManager.NavigateTo("/usercenter");
        }
        else
        {
            var authUrl = AuthUrl + $"/connect/authorize?response_type=code&client_id=Blog_Blazor&redirect_uri={SelfUrl}/login-callback&scope=Blog";
            await JSRuntime.InvokeVoidAsync("openNew", authUrl, "_blank");
        }
    }

    /// <summary>
    /// 点赞
    /// </summary>
    /// <param name="blogId"></param>
    /// <returns></returns>
    public async Task GiveLike(int blogId)
    {
        var respone = await HttpClient.GetAsync($"/api/blog/blog/give-like/{blogId}");
        if (respone.IsSuccessStatusCode)
        {
            int likeCount = Convert.ToInt32(await respone.Content.ReadAsStringAsync());
            BlogList.Find(t => t.Id == blogId).LikeCount = likeCount;
        }
    }

    /// <summary>
    /// 提交博客
    /// </summary>
    /// <returns></returns>
    public async Task SubmitBlog()
    {
        if (userInfo == null)
        {
            await _message.Info("请登录");
            return;
        }
        string url = "/api/blog/blog/blog";
        BlogDto dto = new BlogDto
        {
            Content = BlogText,
            Title = "",
            Tag = "",
            Files = BlogPictures
        };
        StringContent content = new StringContent(JsonSerializer.Serialize(dto), Encoding.UTF8, "application/json");
        var result = await HttpClient.PostAsync(url, content);
        if (result.IsSuccessStatusCode)
        {
            int id = Convert.ToInt32(await result.Content.ReadAsStringAsync());
            BlogListDto blog = new BlogListDto
            {
                Id = id,
                Title = dto.Title,
                Tag = dto.Tag,
                Content = dto.Content,
                Files = BlogPictures,
                CreateTime = DateTime.Now,
                UserId = userInfo.Id,
                UserName = userInfo.UserName,
                Name = userInfo.Name,
                HeadPhoto = userInfo.HeadPhoto,
                LikeCount = 0,
                ReadCount = 0,
                ReplyList = new List<BlogReplyResultDto>()
            };
            BlogList.AddFirst(blog);
            BlogText = "";
            _visible = false;
            fileList.Clear();
            await _message.Success("发表成功");
        }
        else
            await _message.Error("发表失败");
    }

    /// <summary>
    /// 删除回复
    /// </summary>
    /// <param name="id"></param>
    /// <param name="blogId"></param>
    /// <returns></returns>
    public async Task DeleteReply(int id, int blogId)
    {
        string url = $"/api/blog/blog/{id}/reply";
        var result = await HttpClient.DeleteAsync(url);
        if (result.IsSuccessStatusCode)
        {
            var blog = BlogList.Find(t => t.Id == blogId);
            var reply = blog.ReplyList.Find(t => t.BlogReplyId == id);
            blog.ReplyList.Remove(reply);
        }
        else
            await _message.Error("删除失败");
    }

    /// <summary>
    /// 删除博客
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task DeleteBlog(int id)
    {
        string url = $"/api/blog/blog/{id}/blog";
        var result = await HttpClient.DeleteAsync(url);
        if (result.IsSuccessStatusCode)
        {
            var blog = BlogList.Remove(BlogList.Find(t => t.Id == id));
        }
        else
            await _message.Error("删除失败");
    }

    void HandleChange(UploadInfo fileinfo)
    {
        if (fileinfo.File.State == UploadState.Success)
        {
            fileinfo.File.Url = fileinfo.File.ObjectURL;
            BlogPictures += fileinfo.File.Response + ",";
        }
}

public class ResponseModel
{
  public string name { get; set; }

  public string status { get; set; }

  public string url { get; set; }

  public string thumbUrl { get; set; }
}

private void OnVisibleChange(bool visible)
{
  _visible = visible;
}

bool BeforeUpload(UploadFileItem file)
{
  var isJpgOrPng = file.Type == "image/jpeg" || file.Type == "image/png";
  if (!isJpgOrPng)
  {
      _message.Error("只支持jpg和png格式");
  }
  var isLt10M = file.Size / 1024 / 1024 < 10;
  if (!isLt10M)
  {
      _message.Error("请上传小于10M的图片");
  }
  return isJpgOrPng && isLt10M;
}
    }